home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gawk / gawk213b.zoo / test / io.c < prev    next >
C/C++ Source or Header  |  1991-05-31  |  20KB  |  847 lines

  1. /*
  2.  * io.c - routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. #ifndef O_RDONLY
  29. #include <fcntl.h>
  30. #endif
  31.  
  32. #ifndef atarist
  33. #define INVALID_HANDLE (-1)
  34. #else
  35. #define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
  36. #endif
  37.  
  38. static IOBUF *nextfile P((void));
  39. static int inrec P((IOBUF *iop, int getline_redirect));
  40. static int iop_close P((IOBUF *iop));
  41. struct redirect *redirect P((NODE *tree, int *errflg));
  42. static void close_one P((void));
  43. static int close_redir P((struct redirect *rp));
  44. #if (!defined(MSDOS)) && (!defined(atarist))
  45. static int wait_any P((int interesting));
  46. #endif
  47. static IOBUF *gawk_popen P((char *cmd, struct redirect *rp));
  48. static int gawk_pclose P((struct redirect *rp));
  49. static int do_pathopen P((char *file));
  50.  
  51. static struct redirect *red_head = NULL;
  52. static IOBUF *curfile = NULL;
  53.  
  54. extern int output_is_tty;
  55. extern NODE *ARGC_node;
  56. extern NODE *ARGV_node;
  57. extern NODE **fields_arr;
  58.  
  59. static IOBUF *
  60. nextfile()
  61. {
  62.     static int i = 1;
  63.     static int files = 0;
  64.     char *arg;
  65.     int fd = INVALID_HANDLE;
  66.     extern char *arg_assign();
  67.  
  68.     if (curfile != NULL && curfile->cnt != EOF)
  69.         return curfile;
  70.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  71.         arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
  72.         if (*arg == '\0')
  73.             continue;
  74.         if (!arg_assign(arg)) {
  75.             files++;
  76.             fd = devopen(arg, "r");
  77.             if (fd == INVALID_HANDLE)
  78.                 fatal("cannot open file `%s' for reading (%s)",
  79.                     arg, strerror(errno));
  80.                 /* NOTREACHED */
  81.             /* This is a kludge.  */
  82.             unref(FILENAME_node->var_value);
  83.             FILENAME_node->var_value =
  84.                 make_string(arg, strlen(arg));
  85.             FNR = 0;
  86.             i++;
  87.             break;
  88.         }
  89.     }
  90.     if (files == 0) {
  91.         files++;
  92.         /* no args. -- use stdin */
  93.         /* FILENAME is init'ed to "-" */
  94.         /* FNR is init'ed to 0 */
  95.         fd = 0;
  96.     }
  97.     if (fd == INVALID_HANDLE)
  98.         return NULL;
  99.     return curfile = iop_alloc(fd);
  100. }
  101.  
  102. void
  103. set_FNR()
  104. {
  105.     FNR = (int) FNR_node->var_value->numbr;
  106. }
  107.  
  108. void
  109. set_NR()
  110. {
  111.     NR = (int) NR_node->var_value->numbr;
  112. }
  113.  
  114. /*
  115.  * This reads in a record from the input file
  116.  */
  117. static int
  118. inrec(iop, getline_redirect)
  119. IOBUF *iop;
  120. int getline_redirect;
  121. {
  122.     char *begin;
  123.     register int cnt;
  124.     int retval = 0;
  125.  
  126.     cnt = get_a_record(&begin, iop, *RS);
  127.     if (cnt == EOF) {
  128.         cnt = 0;
  129.         retval = 1;
  130.     } else if (!getline_redirect) {
  131.             NR += 1;
  132.             FNR += 1;
  133.     }
  134.     set_record(begin, cnt, 1);
  135.  
  136.     return retval;
  137. }
  138.  
  139. static int
  140. iop_close(iop)
  141. IOBUF *iop;
  142. {
  143.     int ret;
  144.  
  145.     if (iop == NULL)
  146.         return 0;
  147.     errno = 0;
  148.  
  149.     /* Work around bug in UNICOS popen, but it shouldn't hurt elsewhere */
  150.     if (iop->fd < 3)
  151.         ret = 0;
  152.     else
  153.         ret = close(iop->fd);
  154.     if (ret == -1)
  155.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  156.     free(iop->buf);
  157.     free(iop->secbuf);
  158.     if (iop == curfile)
  159.         curfile = NULL;    /* kludge -- gotta do better */
  160.     free((char *)iop);
  161.     return ret == -1 ? 1 : 0;
  162. }
  163.  
  164. void
  165. do_input()
  166. {
  167.     IOBUF *iop;
  168.     extern int exiting;
  169.  
  170.     while ((iop = nextfile()) != NULL) {
  171.         if (inrec(iop, 0) == 0)
  172.             while (interpret(expression_value) && inrec(iop, 0) == 0)
  173.                 ;
  174.         (void) iop_close(iop);
  175.         iop = NULL;
  176.         if (exiting)
  177.             break;
  178.     }
  179. }
  180.  
  181. /* Redirection for printf and print commands */
  182. struct redirect *
  183. redirect(tree, errflg)
  184. NODE *tree;
  185. int *errflg;
  186. {
  187.     register NODE *tmp;
  188.     register struct redirect *rp;
  189.     register char *str;
  190.     int tflag = 0;
  191.     int outflag = 0;
  192.     char *direction = "to";
  193.     char *mode;
  194.     int fd;
  195.  
  196.     switch (tree->type) {
  197.     case Node_redirect_append:
  198.         tflag = RED_APPEND;
  199.     case Node_redirect_output:
  200.         outflag = (RED_FILE|RED_WRITE);
  201.         tflag |= outflag;
  202.         break;
  203.     case Node_redirect_pipe:
  204.         tflag = (RED_PIPE|RED_WRITE);
  205.         break;
  206.     case Node_redirect_pipein:
  207.         tflag = (RED_PIPE|RED_READ);
  208.         break;
  209.     case Node_redirect_input:
  210.         tflag = (RED_FILE|RED_READ);
  211.         break;
  212.     default:
  213.         fatal ("invalid tree type %d in redirect()", tree->type);
  214.         break;
  215.     }
  216.     tmp = force_string(tree_eval(tree->subnode));
  217.     str = tmp->stptr;
  218.     for (rp = red_head; rp != NULL; rp = rp->next)
  219.         if (strlen(rp->value) == tmp->stlen
  220.             && STREQN(rp->value, str, tmp->stlen)
  221.             && ((rp->flag & ~RED_NOBUF) == tflag
  222.             || (outflag
  223.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  224.             break;
  225.     if (rp == NULL) {
  226.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  227.             "redirect");
  228.         emalloc(str, char *, tmp->stlen+1, "redirect");
  229.         memcpy(str, tmp->stptr, tmp->stlen);
  230.         str[tmp->stlen] = '\0';
  231.         rp->value = str;
  232.         rp->flag = tflag;
  233.         rp->offset = 0;
  234.         rp->fp = NULL;
  235.         rp->iop = NULL;
  236.         rp->pid = 0;    /* unlikely that we're worried about init */
  237.         rp->status = 0;
  238.         /* maintain list in most-recently-used first order */
  239.         if (red_head)
  240.             red_head->prev = rp;
  241.         rp->prev = NULL;
  242.         rp->next = red_head;
  243.         red_head = rp;
  244.     }
  245.     while (rp->fp == NULL && rp->iop == NULL) {
  246.         mode = NULL;
  247.         errno = 0;
  248.         switch (tree->type) {
  249.         case Node_redirect_output:
  250.             mode = "w";
  251.             break;
  252.         case Node_redirect_append:
  253.             mode = "a";
  254.             break;
  255.         case Node_redirect_pipe:
  256.             if ((rp->fp = popen(str, "w")) == NULL)
  257.                 fatal("can't open pipe (\"%s\") for output (%s)",
  258.                     str, strerror(errno));
  259.             rp->flag |= RED_NOBUF;
  260.             break;
  261.         case Node_redirect_pipein:
  262.             direction = "from";
  263.             if (gawk_popen(str, rp) == NULL)
  264.                 fatal("can't open pipe (\"%s\") for input (%s)",
  265.                     str, strerror(errno));
  266.             break;
  267.         case Node_redirect_input:
  268.             direction = "from";
  269.             rp->iop = iop_alloc(devopen(str, "r"));
  270.             break;
  271.         default:
  272.             cant_happen();
  273.         }
  274.         if (mode != NULL) {
  275.             fd = devopen(str, mode);
  276.             if (fd > INVALID_HANDLE) {
  277.                 if (fd == fileno(stdin))
  278.                     rp->fp = stdin;
  279.                 else if (fd == fileno(stdout))
  280.                     rp->fp = stdout;
  281.                 else if (fd == fileno(stderr))
  282.                     rp->fp = stderr;
  283.                 else    
  284.                     rp->fp = fdopen(fd, mode);
  285.                 if (isatty(fd))
  286.                     rp->flag |= RED_NOBUF;
  287.             }
  288.         }
  289.         if (rp->fp == NULL && rp->iop == NULL) {
  290.             /* too many files open -- close one and try again */
  291. #ifdef atarist
  292.             if (errno == EMFILE)
  293. #else
  294.             if (errno == ENFILE || errno == EMFILE)
  295. #endif
  296.                 close_one();
  297.             else {
  298.                 /*
  299.                  * Some other reason for failure.
  300.                  *
  301.                  * On redirection of input from a file,
  302.                  * just return an error, so e.g. getline
  303.                  * can return -1.  For output to file,
  304.                  * complain. The shell will complain on
  305.                  * a bad command to a pipe.
  306.                  */
  307.                 *errflg = 1;
  308.                 if (tree->type == Node_redirect_output
  309.                     || tree->type == Node_redirect_append)
  310.                     fatal("can't redirect %s `%s' (%s)",
  311.                         direction, str, strerror(errno));
  312.                 else
  313.                     return NULL;
  314.             }
  315.         }
  316.     }
  317.     if (rp->offset != 0)    /* this file was previously open */
  318.         if (fseek(rp->fp, rp->offset, 0) == -1)
  319.             fatal("can't seek to %ld on `%s' (%s)",
  320.                 rp->offset, str, strerror(errno));
  321.     free_temp(tmp);
  322.     return rp;
  323. }
  324.  
  325. static void
  326. close_one()
  327. {
  328.     register struct redirect *rp;
  329.     register struct redirect *rplast = NULL;
  330.  
  331.     /* go to end of list first, to pick up least recently used entry */
  332.     for (rp = red_head; rp != NULL; rp = rp->next)
  333.         rplast = rp;
  334.     /* now work back up through the list */
  335.     for (rp = rplast; rp != NULL; rp = rp->prev)
  336.         if (rp->fp && (rp->flag & RED_FILE)) {
  337.